home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gawk / gawk213s.zoo / gawk-src-2.13 / eval.c < prev    next >
C/C++ Source or Header  |  1991-07-21  |  29KB  |  1,184 lines

  1. /*
  2.  * eval.c - gawk parse tree interpreter 
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1986, 1988, 1989, 1991 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 1, or (at your option)
  14.  * any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. extern double pow P((double x, double y));
  29. extern double modf P((double x, double *yp));
  30.  
  31. static int eval_condition P((NODE *tree));
  32. static NODE *op_assign P((NODE *tree));
  33. static NODE *func_call P((NODE *name, NODE *arg_list));
  34. static NODE *match_op P((NODE *tree));
  35.  
  36. NODE *_t;        /* used as a temporary in macros */
  37. #ifdef MSDOS
  38. double _msc51bug;    /* to get around a bug in MSC 5.1 */
  39. #endif
  40. NODE *ret_node;
  41. int OFSlen;
  42. int ORSlen;
  43. int OFMTidx;
  44. int CONVFMTidx;
  45.  
  46. /* Macros and variables to save and restore function and loop bindings */
  47. /*
  48.  * the val variable allows return/continue/break-out-of-context to be
  49.  * caught and diagnosed
  50.  */
  51. #define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  52. #define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  53.  
  54. static jmp_buf loop_tag;    /* always the current binding */
  55. static int loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  56. static int func_tag_valid = 0;
  57. static jmp_buf func_tag;
  58. extern int exiting, exit_val;
  59.  
  60. /*
  61.  * This table is used by the regexp routines to do case independant
  62.  * matching. Basically, every ascii character maps to itself, except
  63.  * uppercase letters map to lower case ones. This table has 256
  64.  * entries, which may be overkill. Note also that if the system this
  65.  * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  66.  * defined to the linker, so gawk should not load.
  67.  *
  68.  * Do NOT make this array static, it is used in several spots, not
  69.  * just in this file.
  70.  */
  71. #if 'a' == 97    /* it's ascii */
  72. char casetable[] = {
  73.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  74.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  75.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  76.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  77.     /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  78.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  79.     /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  80.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  81.     /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  82.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  83.     /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  84.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  85.     /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  86.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  87.     /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  88.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  89.     /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  90.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  91.     /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  92.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  93.     /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  94.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  95.     /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  96.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  97.     /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  98.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  99.     /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  100.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  101.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  102.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  103.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  104.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  105.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  106.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  107.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  108.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  109.     '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  110.     '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  111.     '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  112.     '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  113.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  114.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  115.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  116.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  117. };
  118. #else
  119. #include "You lose. You will need a translation table for your character set."
  120. #endif
  121.  
  122. /*
  123.  * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  124.  * statement 
  125.  */
  126. int
  127. interpret(tree)
  128. register NODE *tree;
  129. {
  130.     volatile jmp_buf loop_tag_stack; /* shallow binding stack for loop_tag */
  131.     static jmp_buf rule_tag;/* tag the rule currently being run, for NEXT
  132.                  * and EXIT statements.  It is static because
  133.                  * there are no nested rules */
  134.     register NODE *t = NULL;/* temporary */
  135.     volatile NODE **lhs;    /* lhs == Left Hand Side for assigns, etc */
  136.     volatile NODE *stable_tree;
  137.     int traverse = 1;       /* True => loop thru tree (Node_rule_list) */
  138.  
  139.     if (tree == NULL)
  140.         return 1;
  141.     sourceline = tree->source_line;
  142.     source = tree->source_file;
  143.     switch (tree->type) {
  144.     case Node_rule_node:
  145.         traverse = 0;   /* False => one for-loop iteration only */
  146.         /* FALL THROUGH */
  147.     case Node_rule_list:
  148.         for (t = tree; t != NULL; t = t->rnode) {
  149.             if (traverse)
  150.                 tree = t->lnode;
  151.             sourceline = tree->source_line;
  152.             source = tree->source_file;
  153.             switch (setjmp(rule_tag)) {
  154.             case 0:    /* normal non-jump */
  155.                 /* test pattern, if any */
  156.                 if (tree->lnode == NULL ||
  157.                     eval_condition(tree->lnode))
  158.                     (void) interpret(tree->rnode);
  159.                 break;
  160.             case TAG_CONTINUE:    /* NEXT statement */
  161.                 return 1;
  162.             case TAG_BREAK:
  163.                 return 0;
  164.             default:
  165.                 cant_happen();
  166.             }
  167.             if (!traverse)          /* case Node_rule_node */
  168.                 break;          /* don't loop */
  169.         }
  170.         break;
  171.  
  172.     case Node_statement_list:
  173.         for (t = tree; t != NULL; t = t->rnode)
  174.             (void) interpret(t->lnode);
  175.         break;
  176.  
  177.     case Node_K_if:
  178.         if (eval_condition(tree->lnode)) {
  179.             (void) interpret(tree->rnode->lnode);
  180.         } else {
  181.             (void) interpret(tree->rnode->rnode);
  182.         }
  183.         break;
  184.  
  185.     case Node_K_while:
  186.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  187.  
  188.         stable_tree = tree;
  189.         while (eval_condition(stable_tree->lnode)) {
  190.             switch (setjmp(loop_tag)) {
  191.             case 0:    /* normal non-jump */
  192.                 (void) interpret(stable_tree->rnode);
  193.                 break;
  194.             case TAG_CONTINUE:    /* continue statement */
  195.                 break;
  196.             case TAG_BREAK:    /* break statement */
  197.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  198.                 return 1;
  199.             default:
  200.                 cant_happen();
  201.             }
  202.         }
  203.         RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  204.         break;
  205.  
  206.     case Node_K_do:
  207.         PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  208.         stable_tree = tree;
  209.         do {
  210.             switch (setjmp(loop_tag)) {
  211.             case 0:    /* normal non-jump */
  212.                 (void) interpret(stable_tree->rnode);
  213.                 break;
  214.             case TAG_CONTINUE:    /* continue statement */
  215.                 break;
  216.             case TAG_BREAK:    /* break statement */
  217.                 RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  218.                 return 1;
  219.             default:
  220.                 cant_happen();
  221.             }
  222.         } while (eval_condition(stable_tree->lnod